#include "fileparser.hh"
#include <iostream>
using namespace std;

FileParser::FileParser(const char* fileName, const OutputStream& output)
{
  if(fileName == NULL){
    defaultInit();
    cerr << "File name couldn't be empty!" << endl;   
    return;
  }
  else{
    FILE* stream = fopen(fileName,"r");
    if(stream == NULL){
      defaultInit();
      cerr << "Could not open the file " << fileName << endl; 
      return;
    }
    _fileName = (char*)malloc(sizeof(fileName)+1);
    strcpy(_fileName,fileName);
    long sizeOfFile;
    fseek(stream,0,SEEK_END);
    sizeOfFile = ftell(stream);
    fseek(stream,0,SEEK_SET);
    _buf = (char*)malloc(sizeOfFile+1);
    fread(_buf,1,sizeOfFile,stream);
    _buf[sizeOfFile] = '\0';
    _index = _buf;
    _beginOfLine = _buf;
    _lineNum = 0;
  }
  _output = output;
}

FileParser::~FileParser()
{
  if(_fileName != NULL){
    free(_fileName);
  }
  if(_buf != NULL){
    free(_buf);
  }
  _index = NULL;
  _beginOfLine = NULL;
  _lineNum = 0;
}

FileParser::defaultInit()
{
  _fileName = NULL;
  _buf = NULL;
  _index = NULL;
  _beginOfLine = NULL;
  _lineNum = 0;
}

void FileParser::run()
{
  _curToken = getToken();
  switch(_curToken){
    case TOK_EOF:
      break;
    default:
      segment_list();
      break;
  }
}

void FileParser::segment_list()
{
  segment();
  switch(_curToken){
    case TOK_EOF:
      break;
    default:
      segment_list();
      break;
  }
}

void FileParser::segment()
{
  switch(_curToken){
    case TOK_BACKQUOTE:
      while(_curToken == TOK_BACKQUOTE){
        compiler_directive();
      }
      break;
    default:
      non_backquote_identifier_list();
      while(_curToken == TOK_BACKQUOTE){
        compiler_directive();
      }
      break;
  }
}

void FileParser::non_backquote_identifier_list()
{
  while(_curToken != TOK_BACKQUOTE && _curToken != TOK_EOF){
    _curToken = getToken();
  }
}

void FileParser::compile_directive()
{
  _curToken = getToken(); //skip backquote
  switch(_curToken){
    case TOK_CELLDEFINE:
      celldefine_compiler_directive();
      break;
    case TOK_ENDCELLDEFINE:
      endcelldefine_compiler_directive();
      break;
    case TOK_DEFAULT_NETTYPE:
      default_nettype_compiler_directive();
      break;
    case TOK_DEFINE:
      text_macro_definition();
      break;
    case TOK_IDENTIFIER:
      text_macro_usage();
      break;
    case TOK_UNDEF:
      undefine_compiler_directive();
      break;
    case TOK_IFDEF:
      ifdef_directive();
      break;
    case TOK_IFNDEF:
      ifndef_directive();
      break;
    case TOK_INCLUDE:
      include_compiler_directive();
      break;
    case TOK_RESETALL:
      resetall_compiler_directive();
      break;
    case TOK_LINE:
      line_compiler_directive();
      break;
    case TOK_TIMESCALE:
      timescale_compiler_directive();
      break;
    case TOK_UNCONNECTED_DRIVE:
      unconnected_drive_compiler_directive();
      break;
    case TOK_NOUNCONNECTED_DRIVE:
      nounconnected_drive_compiler_directive();
      break;
    default:
      error();
      break;
  }
}

